/**
 * 单链表节点构造函数
 * @param {*} data 节点值
 * @param {MyNode} next 指向下一个节点的引用
 */
function MyNode(data, next) {
	this.data = data;
	this.next = next;
}

/**
 * 单链表对象构造函数
 */
function SingleLinkedList() {
	/**
	 * 初始化头结点，头结点是链表索引的开始，其不存放内容，可以理解为头结点是一个链表的标识
	 */
	this.head = new MyNode(null, null);
	/**
	 * 在链表尾部插入元素的方法
	 * @param {*} data 插入元素值
	 */
	this.add = (data) => {
		// 从头开始往后遍历，当遍历到某个节点后面为null是说明这是最后一个节点
		let node = this.head;
		while (node.next !== null) {
			node = node.next;
		}
		// 这时node的下一个是空的了，就实例化一个节点加进去
		let newNode = new MyNode(data, null);
		node.next = newNode;
	}
	/**
	 * 指定位置插入元素的方法
	 * @param {Number} index 索引，0表示第一个节点（也就是头结点的后一个）
	 * @param {*} data 插入节点值
	 */
	this.insert = (index, data) => {
		// 建立一个引用指向第index - 1个节点处
		let node = this.head;
		// 可以把头结点理解为第-1个节点
		for (let i = -1; i < index - 1; i++) {
			node = node.next;
			// 判断是否越界
			if (node === null) {
				console.error('索引越界！');
				return;
			}
		}
		// 这是node已经指向第index - 1个节点了
		// 先实例化新节点，并把新节点的下一个指向node的下一个
		let newNode = new MyNode(data, node.next);
		// 再把node的下一个指向新节点
		node.next = newNode;
	}
	/**
	 * 删除指定索引处的节点
	 * @param {Number} index 待删除节点索引
	 */
	this.delete = (index) => {
		// 建立一个引用指向第index - 1个节点处
		let node = this.head;
		// 可以把头结点理解为第-1个节点
		for (let i = -1; i < index - 1; i++) {
			node = node.next;
			// 判断是否越界
			if (node.next === null) {
				console.error('索引越界！');
				return;
			}
		}
		// 直接把index - 1节点的下一个指向index + 1个节点即可
		node.next = node.next.next;
	}
	/**
	 * 修改指定索引处节点值
	 * @param {Number} index 待修改节点索引
	 * @param {*} data 修改值
	 */
	this.set = (index, data) => {
		// 建立一个引用指向第index个节点处
		let node = this.head;
		for (let i = -1; i < index; i++) {
			node = node.next;
			// 判断是否越界
			if (node.next === null) {
				console.error('索引越界！');
				return;
			}
		}
		// 这时node已经指向了第index个节点了，直接修改其值即可
		node.data = data;
	}
	/**
	 * 获取第index个节点的值
	 * @param {Number} index 待获取节点值
	 * @returns 节点值
	 */
	this.get = (index) => {
		// 建立一个引用指向第index个节点处
		let node = this.head;
		for (let i = -1; i < index; i++) {
			node = node.next;
			// 判断是否越界
			if (node.next === null) {
				console.error('索引越界！');
				return;
			}
		}
		// 直接返回即可
		return node.data;
	}
	/**
	 * 打印链表
	 */
	this.print = () => {
		let printResult = '○';
		let node = this.head;
		while ((node = node.next) !== null) {
			printResult = printResult + ' -> ' + node.data;
		}
		console.log(printResult);
	}
}

// 进行测试
let list = new SingleLinkedList();
// 插入五个元素
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.print();
// 在指定位置插入
list.insert(0, 0);
list.insert(4, 10);
list.print();
// 删除
list.delete(4);
list.print();
// 修改
list.set(2, 10);
list.print();
// 查个元素
console.log(list.get(3));